import cv2
import numpy as np


# 鼠标事件


class ImgCoordinate:

    def __init__(self,show_h, show_w):
        self.flag = None  # 鼠标操作类型
        self.horizontal = None  # 原图是否超出显示图片
        self.vertical = None  # 原图是否超出显示图片
        self.flag_hor = None  # 鼠标是否在水平滚动条上
        self.flag_ver = None  # 鼠标是否在垂直滚动条上

        self.dx = None  # 显示图片相对于原图的坐标
        self.dy = None  # 显示图片相对于原图的坐标
        self.sx = None  # 滚动块相对于滚动条的坐标
        self.sy = None  # 滚动块相对于滚动条的坐标

        self.presentX = None
        self.presentY = None #左键点击后，此刻的X,y坐标
        self.fixedPoint = [] #定点，为了之后自动跳转坐标点
        self.fixedPointXY = []
        self.fixedPointSXSY = []
        self.moveCount = 1
        self.dst = None
        self.x1 = None
        self.y1 = None
        self.x2 = None
        self.y2 = None
        self.x3 = None
        self.y3 = None  # 中间变量

        self.f1 = None
        self.f2 = None  # 原图可移动部分占滚动条可移动部分的比例

        # self.zoom =

        self.scroll_har = None  # 滚动条水平垂直长度
        self.scroll_var = None  # 滚动条水平垂直长度
        self.img_w = None  # 原图宽高
        self.img_h = None  # 原图宽高
        self.img = None
        # self.dst1 = None
        self.win_w = None  # 窗口宽高
        self.win_h = None  # 窗口宽高
        self.show_w = None  # 显示图片宽高
        self.show_h = None  # 显示图片宽高
        print('>>>>>>>>>>>>>>>>>>>>>>>>>')
        print(show_h)
        self.show_h, self.show_w = int(show_h), int(show_w)  # 显示图片宽高

    def imgCoordinate(self, img_original, moveType=0, offsetDxDy=None, offsetXY=None, offsetSxSy=None):
        """"
            path: 图片路径

        """

        self.fixedPoint.clear()
        self.fixedPointXY.clear()
        self.fixedPointSXSY.clear()
        #img_original = cv2.imdecode(np.fromfile(path, dtype=np.uint8), -1)
        #img_original = cv2.imread(path)  # 此处需换成大于img_w * img_h的图片
        img_original_h, img_original_w = img_original.shape[0:2]  # 原图宽高
        cv2.namedWindow('img', cv2.WINDOW_AUTOSIZE)
        cv2.moveWindow("img", 300, -10)
        self.img = img_original.copy()
        self.img_h, self.img_w = self.img.shape[0:2]  # 原图宽高
        #self.show_h, self.show_w = 800, 1000  # 显示图片宽高
        self.horizontal, self.vertical = 0, 0  # 原图是否超出显示图片
        self.dx, self.dy = 0, 0  # 显示图片相对于原图的坐标
        self.scroll_w = 16  # 滚动条宽度
        self.sx, self.sy = 0, 0  # 滚动块相对于滚动条的坐标
        self.flag, self.flag_hor, self.flag_ver = 0, 0, 0  # 鼠标操作类型，鼠标是否在水平滚动条上，鼠标是否在垂直滚动条上
        self.x1, self.y1, self.x2, self.y2, self.x3, self.y3 = 0, 0, 0, 0, 0, 0  # 中间变量
        self.win_w, self.win_h = self.show_w + self.scroll_w, self.show_h + self.scroll_w  # 窗口宽高
        self.scroll_har, self.scroll_var = ((self.win_w * self.show_w / self.img_w),
                                            self.win_h * self.show_h / self.img_h)  # 滚动条水平垂直长度
        print(
            f'窗口宽win_w:{self.win_w},显示图片宽show_w:{self.show_w},原图宽img_w:{self.img_w},h{self.img_h},滚动条scroll_har:{self.scroll_har},{self.scroll_var}')
        wheel_step, zoom = 0.05, 1  # 缩放系数， 缩放值
        zoom_w, zoom_h = self.img_w, self.img_h  # 缩放图宽高
        self.f1, self.f2 = ((self.img_w - self.show_w) / (self.win_w - self.scroll_har),
                            (self.img_h - self.show_h) / (self.win_h - self.scroll_var))  # 原图可移动部分占滚动条可移动部分的比例

        if self.img_h <= self.show_h and self.img_w <= self.show_w:
            cv2.imshow("img", img)
        else:
            if self.img_w > self.show_w:
                self.horizontal = 1
            if self.img_h > self.show_h:
                self.vertical = 1
            i = self.img[self.dy:self.dy + self.show_h, self.dx:self.dx + self.show_w]
            self.dst = i.copy()
        cv2.resizeWindow("img", self.win_w, self.win_h)
        self.moveCount = 1
        params = {'moveType': moveType, 'offsetDxDy': offsetDxDy, 'offsetXY': offsetXY, 'offsetSxSy': offsetSxSy,'movePointIndex': self.moveCount}
        cv2.setMouseCallback('img', self.mouse, params)

        # if moveType == 1:
        #     self.dx = offsetDxDy[0][0]
        #     self.dy = offsetDxDy[0][1]
        #     self.sx = offsetSxSy[0][0]
        #     self.sy = offsetSxSy[0][1]
        #
        #     self.flag_ver = 1
        #     print(f'self.sx:{self.sx}')
        #     self.mouse(cv2.EVENT_LBUTTONDOWN, offsetXY[0][0], offsetXY[0][1],1,params)
        #     self.moveImg(offsetXY[0][0], offsetXY[0][1])

        cv2.waitKey()
        cv2.destroyAllWindows()

    def mouse(self, event, x, y, flags, params):
        moveType = params.get('moveType')
        offsetDxDy = params.get('offsetDxDy')
        offsetXY = params.get('offsetXY')
        offsetSxSy = params.get('offsetSxSy')
        movePointIndex = self.moveCount #params.get('movePointIndex',0)
        if event == cv2.EVENT_LBUTTONDOWN:  # 左键点击
            if self.flag == 0:
                if self.horizontal and 0 < x < self.win_w and self.win_h - self.scroll_w < y < self.win_h:
                    self.flag_hor = 1  # 鼠标在水平滚动条上
                elif self.vertical and self.win_w - self.scroll_w < x < self.win_w and 0 < y < self.win_h:
                    self.flag_ver = 1  # 鼠标在垂直滚动条上
                if self.flag_hor or self.flag_ver:
                    self.flag = 1  # 进行滚动条垂直
                    self.x1, self.y1, self.x2, self.y2, self.x3, self.y3 = x, y, self.dx, self.dy, self.sx, self.sy  # 使鼠标移动距离都是相对于初始滚动条点击位置，而不是相对于上一位置
        elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):  # 按住左键拖曳
            self.moveImg(x, y)
            # print(dy, dy + show_h, dx, dx + show_w)
            # self.dst = img1.copy()
        elif event == cv2.EVENT_LBUTTONUP:  # 左键释放

            self.lButtonUp()
        elif event == cv2.EVENT_RBUTTONDOWN:
            self.presentX = x
            self.presentY = y
            print(f'x-->{x},y-->{y}')
            print(f'dx-->{self.dx},dx-->{self.dy}')
            print(f'sx-->{self.sx},sy-->{self.sy}')

            self.fixedPoint.append((self.dx,self.dy))
            self.fixedPointXY.append((x,y))
            self.fixedPointSXSY.append((self.sx,self.sy))
            print(f'movePointIndex{str(movePointIndex)}')
            piontLen = 10000
            if offsetDxDy is not None:
                piontLen = len(offsetDxDy)
            if movePointIndex == piontLen:
                cv2.waitKey(500)
                cv2.destroyAllWindows()
            if moveType == 1 and movePointIndex != piontLen:
                self.dx = offsetDxDy[movePointIndex][0]
                self.dy = offsetDxDy[movePointIndex][1]
                self.sx = offsetSxSy[movePointIndex][0]
                self.sy = offsetSxSy[movePointIndex][1]
                xPoint = offsetXY[movePointIndex][0]
                yPoint = offsetXY[movePointIndex][1]

                self.flag_ver = 1
                print(f'self.sx:{self.sx}')
                self.moveCount += 1
                params = {'moveType': moveType, 'offsetDxDy': offsetDxDy, 'offsetXY': offsetXY,
                          'offsetSxSy': offsetSxSy,'movePointIndex': self.moveCount}

                self.mouse(cv2.EVENT_LBUTTONDOWN, xPoint, yPoint, 1, params)
                self.moveImg(xPoint, yPoint)
        if self.horizontal and self.vertical:
            self.sx, self.sy = int(self.sx), int(self.sy)
            # 对dst1画图而非dst，避免鼠标事件不断刷新使显示图片不断进行填充
            dst1 = cv2.copyMakeBorder(self.dst, 0, self.scroll_w, 0, self.scroll_w, cv2.BORDER_CONSTANT,
                                      value=[255, 255, 255])
            cv2.rectangle(dst1, (self.sx, self.show_h), (int(self.sx + self.scroll_har), self.win_h),
                          (181, 181, 181), -1)  # 画水平滚动条
            cv2.rectangle(dst1, (self.show_w, self.sy), (self.win_w, int(self.sy + self.scroll_var)),
                          (181, 181, 181), -1)  # 画垂直滚动条
        elif self.horizontal == 0 and self.vertical:
            self.sx, self.sy = int(self.sx), int(self.sy)
            dst1 = cv2.copyMakeBorder(self.dst, 0, 0, 0, self.scroll_w, cv2.BORDER_CONSTANT, value=[255, 255, 255])
            cv2.rectangle(dst1, (self.show_w, self.sy), (self.win_w, int(self.sy + self.scroll_var)),
                          (181, 181, 181), -1)  # 画垂直滚动条
        elif self.horizontal and self.vertical == 0:
            self.sx, self.sy = int(self.sx), int(self.sy)
            dst1 = cv2.copyMakeBorder(self.dst, 0, self.scroll_w, 0, 0, cv2.BORDER_CONSTANT, value=[255, 255, 255])
            cv2.rectangle(dst1, (self.sx, self.show_h), (int(self.sx + self.scroll_har), self.win_h),
                          (181, 181, 181), -1)  # 画水平滚动条
        cv2.imshow("img", dst1)
        cv2.waitKey(1)

    def moveImg(self, x, y):
        if self.flag == 1:
            if self.flag_hor:
                w = (x - self.x1) / 2  # 移动宽度
                self.dx = self.x2 + w * self.f1  # 原图x
                if self.dx < 0:  # 位置矫正
                    self.dx = 0
                elif self.dx > self.img_w - self.show_w:
                    self.dx = self.img_w - self.show_w
                self.sx = self.x3 + w  # 滚动条x
                if self.sx < 0:  # 位置矫正
                    self.sx = 0
                elif self.sx > self.win_w - self.scroll_har:
                    self.sx = self.win_w - self.scroll_har
            if self.flag_ver:
                h = y - self.y1  # 移动高度
                self.dy = self.y2 + h * self.f2  # 原图y
                if self.dy < 0:  # 位置矫正
                    self.dy = 0
                elif self.dy > self.img_h - self.show_h:
                    self.dy = self.img_h - self.show_h
                self.sy = self.y3 + h  # 滚动条y
                if self.sy < 0:  # 位置矫正
                    self.sy = 0
                elif self.sy > self.win_h - self.scroll_var:
                    self.sy = self.win_h - self.scroll_var
            self.dx, self.dy = int(self.dx), int(self.dy)
            img1 = self.img[self.dy:self.dy + self.show_h, self.dx:self.dx + self.show_w]  # 截取显示图片
            self.dst = img1.copy()

    def lButtonUp(self):
        self.flag, self.flag_hor, self.flag_ver = 0, 0, 0
        self.x1, self.y1, self.x2, self.y2, self.x3, self.y3 = 0, 0, 0, 0, 0, 0
        print(self.dy, self.dy + self.show_h, self.dx, self.dx + self.show_w)


if __name__ == '__main__':
    img = ImgCoordinate()
    img.imgCoordinate("F:\\P_008.jpg", 1, 769, 380, [(630, 796), (392, 406)])
# 996 1596 830 1630
# x-->769,y-->380
